package top.surgeqi.security.jwt.config.extend;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Primary;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import top.surgeqi.security.jwt.contants.AuthConstants;
import top.surgeqi.security.jwt.exception.CustomerAuthenticationException;
import top.surgeqi.security.jwt.utils.BpwdEncoderUtil;

/**
 * <p><em>Created by qipp on 2020/2/27 14:45</em></p>
 * 用户名密码认证器
 *
 * @author <a href="https://gitee.com/qipengpai">qipp</a>
 * @since 1.0.1
 */
@Component
@Primary
@Slf4j
public class UsernamePasswordAuthenticator extends AbstractPrepareExtendAuthenticator {

    /**
     * 用户名密码认证
     */
    private final static String AUTH_TYPE = "password";

    /**
     * 根据用户名密码方式进行认证
     *
     * @param entity 扩展认证对象
     * @return org.surge.oauth2common.model.UserAccount
     * @author qipp
     */
    @Override
    public UserDetails authenticate(ExtendAuthenticationEntity entity) {

        // 获取用户名密码
        String username = entity.getAuthParameter(AuthConstants.AUTH_USERNAME);
        String password = entity.getAuthParameter(AuthConstants.AUTH_PASSWORD);

        // 用户名或密码为空
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            throw new CustomerAuthenticationException("用户名或密码为空！");
        }
        // 根据用户名或手机号查询用户账户
        UserDetails userDetails = abstractUserDetailsService.selectByUserName(username);
        if (null == userDetails) {
            throw new CustomerAuthenticationException("用户不存在！");
        }
        // 验证密码正确性
        if (!BpwdEncoderUtil.matches(password, userDetails.getPassword())) {
            throw new CustomerAuthenticationException("密码错误！");
        }
        // 验证用户可用性并组合用户账户对象与角色权限
        return this.validateAndComposeUser(userDetails);
    }

    /**
     * 用户名密码方式
     * <p>认证类型为空时为用户名密码方式</p>
     * {@inheritDoc}
     */
    @Override
    public boolean support(ExtendAuthenticationEntity entity) {
        // 认证类型
        String authType = entity.getAuthType();
        return StringUtils.isEmpty(authType) || authType.equals(AUTH_TYPE);
    }
}
